//SD_C_Tool.cpp---------------数独类中工具方法的定义
//
//	void SD_C::Init_q():					//用全局数组q1初始化q
//	void SD_C::Init_s();					//初始化
//	void SD_C::SimpleInit_s();				//简单初始化
//	void SD_C::Print_q(int);				//打印结果数组q
//	void SD_C::Out_q();						//输出数组q到全局数组q0中
//
//	int SD_C::CountOneBit(short);			//计算二进制数中1的个数
//	int SD_C::HighestOneBit(short);			//取最高位1的位数
//	void SD_C::Print_bit(short);  			//打印九位二进制数
//
//	void SD_C::Print_s();					//打印s数组当前状态
//	int SD_C::Check_s();					//检查s数组解题进度
//	void SD_C::Update_q();					//通过s数组更新答题数组q
//
//v.1.0------------------------------------------------------------------

#include<iostream>
#include<cmath>

#include"SD_class.h"
#include"SD_ver.h"

using namespace std;

//1.初始化q
void SD_C::Init_q()
{
	for (int i = 0; i < 9; i++)
		for (int j = 0; j < 9; j++)
            q[i][j] = q4[i][j];
}

//2.初始化s
void SD_C::Init_s()
{
    cout << "开始初始化";
    //根据数组q的初始值初始化数组s
    //Print_s();
	for (int i = 0; i < 9; i++)
	{
		for (int j = 0; j < 9; j++)
		{
			if (q[i][j] == 0)
                s[i][j] = 511;              //二进制为0b1 1111 1111
			else
                s[i][j] = 1 << (q[i][j] - 1);
            cout<<"-";
		}

	}
    //对数组s进行去重操作（运用唯一法）
	for (int i = 0; i < 9; i++)
	{
		for (int j = 0; j < 9; j++)
			FindSole(i, j);					//去重
		cout<<"-";
	}
    t = 0;                                  //重置解个数存储器
    //打印数独题目	
    cout <<"初始化结束"<<endl;
    //<<"目前数组标志状态："<<endl;
    //Print_s();
    //cout<<"目前数组填空状态："<<endl;
    //Print_q(1);
    //cout<<"-------------------------------------------------------------------------------------------------------------------------"<<endl;
}

//3.简单初始化数组s并打印
void SD_C::SimpleInit_s()
{
    //cout << "开始简单初始化"<<endl;
	for (int i = 0; i < 9; i++)
	{
		for (int j = 0; j < 9; j++)
		{
			if (q[i][j] == 0)
                s[i][j] = 511;
			else
                s[i][j] = 1 << (q[i][j] - 1);
            //cout<<"-";
		}
	}
    t = 0;                                  //重置解个数存储器
    //cout <<"简单初始化结束"<<endl;
}

//4.打印结果数组q
void SD_C::Print_q(int a)
{
	int Block = 0;
	
	for (int i = 0; i < 9; i++)
	{
		for (int j = 0; j < 9; j++)
		{
			cout << q[i][j];
			if (j == 2 || j == 5)
				cout << "  ";
			if (j == 8)
			{
				cout << endl;
                if (i == 2 || i == 5)
					cout << endl;
			}
			if (q[i][j] == 0)
				Block++;
		}
	}
	if (a)
		cout << "已知" << 81 - Block << "个空。"<<endl<<endl;
}

//5.输出结果q到全局数组q0
void SD_C::Out_q()
{
	for (int i = 0; i < 9; i++)
		for (int j = 0; j < 9; j++)
			q0[i][j] = this->q[i][j];
}


//6.计算二进制数中1的个数
int SD_C::CountOneBit(short a)
{
	int n = 0;
    while (a) {
		n++;
        a &= (a - 1);
	}
	return n;
}

//7.取二进制数最高位1的位数
//   第次右移,得到从高位开始的
//   一串1,再减去自身右移一位
//   后的数,得到仅高位有1的数
int SD_C::HighestOneBit(short a)
{
    a |= (a >> 1);
    a |= (a >> 2);
    a |= (a >> 4);
    a |= (a >> 8);
    return a - (a >> 1);
}

//8.打印9位二进制数
void SD_C::Print_bit(short a)
{
    short b;
	for (int i = 8; i >= 0; i--)
	{
        b = a & (1 << i);
        if (b == 0)
			cout << 0;
		else
			cout << 1;
	}
    //cout << " ";
}

//9.打印当前数独解题状态
void SD_C::Print_s()
{
	for (int i = 0; i < 9; i++)
	{
		for (int j = 0; j < 9; j++)
		{
            Print_bit(s[i][j]);
            cout<<"-"<<q[i][j]<<" ";
			if (j == 2 || j == 5)
				cout << "  ";
			if (j == 8)
			{
				cout << endl;
				if (i == 2 || i == 5 || i == 8)
					cout << endl;
			}
		}
	}
	cout << endl;
}

//10.检查解题进度
//		@return		 0  完成
//					 1  未完成
//					-1  出错
int SD_C::Check_s()
{
    //cout<<"check"<<endl;
	//可选判断
	for (int j = 0; j < 9; j++)
		for (int i = 0; i < 9; i++)
            if (s[i][j] == 0)
            {
                //cout<<"候选数为0，出错！"<<endl;
                return -1;
            }
    short sum_row;		//行
    short sum_col;		//列
    short sum_squ;		//宫
		
	for (int i = 0; i < 9; i++)
	{
        sum_row = sum_col = sum_squ = 0;
		//行、列(row\col)
		for (int j = 0; j < 9; j++)
		{
			//累加9个空的候选数，结果应当为0b1 1111 1111
            sum_row |= s[i][j];		//i行
            sum_col |= s[j][i];		//i列
		}
		//宫(squ)
		for (int i0 = i / 3 * 3; i0 < i / 3 * 3 + 3; i0++)
			for (int j0 = i % 3 * 3; j0 < i % 3 * 3 + 3; j0++)
                sum_squ |= s[i0][j0];	//i宫
				
        if (sum_row != 0x1ff || sum_col != 0x1ff || sum_squ != 0x1ff)
        {
//            cout<<"第"<<i+1<<"列:";
//            Print_bit(sum_col);
//            cout<<endl<<"第"<<i+1<<"行:";
//            Print_bit(sum_row);
//            cout<<endl<<"第"<<i+1<<"宫:";
//            Print_bit(sum_squ);
//            cout<<endl<<"填空出错，和不为1 1111 1111"<<endl;
			return -1;						//有一个不为0b1 1111 1111，即0x1ff，表示出错
        }
	}
    for (int i = 0; i < 9; i++)
    {
        for (int j = 0; j < 9; j++)
        {
            if (CountOneBit(s[i][j]) > 1)
            {
                //cout<<"候选数多于1，未完成"<<endl;
                return 1;
            }
        }
    }
    //cout<<"完成！"<<endl;
	return 0;								//排除以上所有情况后，表示所有空都填完了
}

//11.通过数组s更新数组q
void SD_C::Update_q()
{
	for (int i = 0; i < 9; i++)
	{
		for (int j = 0; j < 9; j++)
		{
            switch (s[i][j])
			{
                case 1:     {q[i][j] = 1;break;}    //单个候选数
                case 2:     {q[i][j] = 2;break;}
                case 4:     {q[i][j] = 3;break;}
                case 8:     {q[i][j] = 4;break;}
                case 16:    {q[i][j] = 5;break;}
                case 32:    {q[i][j] = 6;break;}
                case 64:    {q[i][j] = 7;break;}
                case 128:   {q[i][j] = 8;break;}
                case 256:   {q[i][j] = 9;break;}
                case 0:     {q[i][j] = -1;break;}   //出错，无候选数
                default:    {q[i][j] = 0;break;}    //多个候选数
			}
		}
	}
}
